home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / text / hyper / hsc_source.lha / hsc / source / ugly / infile.c < prev    next >
C/C++ Source or Header  |  1996-11-25  |  23KB  |  1,081 lines

  1. /*
  2.  * ugly/infile.c
  3.  *
  4.  * ugly input file functions
  5.  *
  6.  * Copyright (C) 1995,96  Thomas Aglassinger
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * updated: 25-Nov-1996
  23.  * created:  8-Jul-1995
  24.  */
  25.  
  26. /*
  27.  * TODO:
  28.  *
  29.  * - handle errors within expstr (no mem)
  30.  * - more elegant handling of inunget( '\n' );
  31.  */
  32.  
  33. /*
  34.  * includes
  35.  */
  36. #include <ctype.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40.  
  41. #include "utypes.h"
  42. #include "expstr.h"
  43. #include "ustring.h"
  44. #include "fname.h"              /* for CRLF_SHIT */
  45.  
  46. #define NOEXTERN_UGLY_FILE_H
  47. #include "infile.h"
  48. #include "umemory.h"
  49.  
  50. /* buffer size for fgets() in ugly_infgetc() */
  51. #define INF_FGETS_BUFSIZE 1024
  52.  
  53. /*
  54.  * global vars
  55.  */
  56. STRPTR FNAME_STDIN = "STDIN";   /* filename for stdin (CONSTANT) */
  57.  
  58. /*
  59.  * debugging defines
  60.  */
  61. #define DINF "*infile* "
  62.  
  63. #ifdef D
  64. #undef D
  65. #endif
  66.  
  67. #if DEBUG_UGLY_INFILE | 0
  68. #define D( x ) x
  69. #else
  70. #define D( x )                  /* nufin */
  71. #endif
  72.  
  73. /*
  74.  * local vars
  75.  */
  76.  
  77. /* forward references */
  78. BOOL infget_skws(INFILE * inpf);
  79. static VOID del_infilepos_nddata(APTR data);
  80.  
  81. /*
  82.  *
  83.  * local functions (not exported into header)
  84.  *
  85.  */
  86.  
  87. /*
  88.  * default_whtspc, default_normch
  89.  *
  90.  * default methods for infgetw() to determine if
  91.  * a char is a whitespace or normal char.
  92.  */
  93. BOOL default_whtspc(int ch)
  94. {
  95.     if (strchr(" \t", ch) != NULL)
  96.         return TRUE;
  97.     else
  98.         return FALSE;
  99. }
  100.  
  101. BOOL default_normch(int ch)
  102. {
  103.     if (isalnum(ch) || (ch == '_'))
  104.         return TRUE;
  105.     else
  106.         return FALSE;
  107. }
  108.  
  109. /*
  110.  *-------------------------------------
  111.  * constructor/destructor
  112.  *-------------------------------------
  113.  */
  114.  
  115. /*
  116.  * reset_inpf
  117.  *
  118.  * reset a INFILE struct (set all items to NULL)
  119.  * (only called by con/destructor)
  120.  */
  121. static VOID reset_infile(INFILE * inpf)
  122. {
  123.     inpf->infile = NULL;
  124.     inpf->filename = NULL;
  125.     inpf->lnbuf = NULL;
  126.     inpf->wordbuf = NULL;
  127.     inpf->wspcbuf = NULL;
  128.     inpf->filepos = 0;
  129.     inpf->pos_x = 0;
  130.     inpf->pos_y = 0;
  131.     inpf->wpos_x = 0;
  132.     inpf->wpos_y = 0;
  133.     inpf->base_x = 0;
  134.     inpf->base_y = 0;
  135.     inpf->pos_list = NULL;
  136.     inpf->pos_count = 0;
  137.     inpf->eof_reached = FALSE;
  138.     inpf->out_of_mem = FALSE;
  139.     inpf->skipped_ws = FALSE;
  140.     inpf->closed = FALSE;
  141.     inpf->is_nc = NULL;
  142.     inpf->is_ws = NULL;
  143. }
  144.  
  145. /*
  146.  * remove INFILE structure
  147.  */
  148. static VOID del_infile(INFILE * inpf)
  149. {
  150.     if (inpf)
  151.     {
  152.         D(
  153.              {
  154.              fprintf(stderr, DINF "close file");
  155.              if (inpf->filename)
  156.              fprintf(stderr, " \"%s\"", inpf->filename);
  157.              fprintf(stderr, "\n");
  158.              }
  159.         );
  160.  
  161.         if (inpf->pos_count)
  162.         {
  163.             inpf->closed = TRUE;
  164.             D(fprintf(stderr, DINF "  (%lu fpos-req left)\n",
  165.                       inpf->pos_count));
  166.         }
  167.         else
  168.         {
  169.             /* close file */
  170.             if (inpf->infile)
  171.                 fclose(inpf->infile);
  172.  
  173.             /* remove pos-requests */
  174.             del_dllist(inpf->pos_list);
  175.  
  176.             /* release mem */
  177.             ufreestr(inpf->filename);
  178.             del_estr(inpf->lnbuf);
  179.             del_estr(inpf->wordbuf);
  180.             del_estr(inpf->wspcbuf);
  181.  
  182.             /* reset all items */
  183.             reset_infile(inpf);
  184.  
  185.             /* release whole structure */
  186.             ufree(inpf);
  187.         }
  188.     }
  189. }
  190.  
  191. /*
  192.  * init INFILE structure
  193.  */
  194. static INFILE *init_infile(CONSTRPTR name, size_t buf_step, size_t word_step)
  195. {
  196.     INFILE *inpf = (INFILE *) umalloc(sizeof(INFILE));
  197.  
  198.     if (inpf)
  199.     {
  200.         /* check for buffer-stepsize */
  201.         if (!buf_step)
  202.             buf_step = IF_BUFFER_VALUE;
  203.         if (!word_step)
  204.             word_step = IF_BUFFER_VALUE;
  205.  
  206.         /* reset all items */
  207.         reset_infile(inpf);
  208.  
  209.         /* clone filename (NULL=stdin) */
  210.         if (name)
  211.             inpf->filename = strclone(name);
  212.  
  213.         /* init wordbuffers */
  214.         inpf->lnbuf = init_estr(buf_step);
  215.         inpf->wordbuf = init_estr(word_step);
  216.         inpf->wspcbuf = init_estr(word_step);
  217.         inpf->pos_list = init_dllist(del_infilepos_nddata);
  218.         inpf->pos_count = 0;
  219.  
  220.         /* check if init ok */
  221.         if (!((inpf->filename || !(name))
  222.               && inpf->lnbuf
  223.               && inpf->wordbuf
  224.               && inpf->wspcbuf))
  225.         {
  226.             /* remove infile, */
  227.             /* set return value to NULL */
  228.             del_infile(inpf);
  229.             inpf = NULL;
  230.         }
  231.     }
  232.  
  233.     return (inpf);
  234. }
  235.  
  236. /*
  237.  *=====================================
  238.  *
  239.  * exported functions
  240.  *
  241.  *=====================================
  242.  */
  243.  
  244. /*
  245.  *-------------------------------------
  246.  * functions to get info about infile
  247.  *-------------------------------------
  248.  */
  249.  
  250. /*
  251.  * infget_x
  252.  *
  253.  * get colum of current line
  254.  */
  255. ULONG infget_x(INFILE * inpf)
  256. {
  257.     return (inpf->pos_x + inpf->base_x);
  258. }
  259.  
  260. /*
  261.  * infget_y
  262.  *
  263.  * get current line
  264.  */
  265. ULONG infget_y(INFILE * inpf)
  266. {
  267.     return (inpf->pos_y + inpf->base_y);
  268. }
  269.  
  270. /*
  271.  * infget_wx
  272.  *
  273.  * get colum of current word
  274.  */
  275. ULONG infget_wx(INFILE * inpf)
  276. {
  277.     return (inpf->wpos_x + inpf->base_x);
  278. }
  279.  
  280. /*
  281.  * infget_y
  282.  *
  283.  * get line of current word
  284.  */
  285. ULONG infget_wy(INFILE * inpf)
  286. {
  287.     return (inpf->wpos_y + inpf->base_y);
  288. }
  289.  
  290. /*
  291.  * infget_skws
  292.  *
  293.  * get status of skipped_ws
  294.  */
  295. BOOL infget_skws(INFILE * inpf)
  296. {
  297.     return (inpf->skipped_ws);
  298. }
  299.  
  300. /*
  301.  * infget_fname
  302.  *
  303.  * get name of file
  304.  */
  305. STRPTR infget_fname(INFILE * inpf)
  306. {
  307.     if (inpf->filename)
  308.         return (inpf->filename);
  309.     else
  310.         return (FNAME_STDIN);
  311. }
  312.  
  313. /*
  314.  * infeof
  315.  *
  316.  * check if end of input file reached
  317.  *
  318.  * params: inpf...input file to check
  319.  * result: if end of input file reached, 0 is returned,
  320.  *         else a value < 0 (compare feof() of some
  321.  *         compilers)
  322.  */
  323. int infeof(INFILE * inpf)
  324. {
  325.     if (inpf->eof_reached == TRUE)
  326.         return EOF;
  327.     else
  328.         return 0;
  329. }
  330.  
  331. /*
  332.  * infget_cws (get current whites spaces)
  333.  *
  334.  * get string that contains all white-spaces
  335.  * skipped within the last call of infgetw()
  336.  */
  337. STRPTR infgetcws(INFILE * inpf)
  338. {
  339.     return (estr2str(inpf->wspcbuf));
  340. }
  341.  
  342. /*
  343.  * infget_cw (get current word)
  344.  *
  345.  * get string that contains all chars
  346.  * read within the last call of infgetw()
  347.  */
  348. STRPTR infgetcw(INFILE * inpf)
  349. {
  350.     return (estr2str(inpf->wordbuf));
  351. }
  352.  
  353. /*
  354.  *-------------------------------------
  355.  * functions to set methods
  356.  *-------------------------------------
  357.  */
  358.  
  359. /*
  360.  * set_inf_whtspc
  361.  *
  362.  * set function to check if a char is a whitespace.
  363.  * this func is called by infgetw() to determine if
  364.  * the begining of a word is reached.
  365.  */
  366. void set_whtspc(INFILE * inpf, BOOL(*iswsfn) (int ch))
  367. {
  368.     if (inpf)
  369.         inpf->is_ws = iswsfn;
  370. }
  371.  
  372. /*
  373.  * set_inf_normch
  374.  *
  375.  * set function to check if a char is a "normal" char.
  376.  * this function is called by infgetw() to determine if
  377.  * the end of a word is reached
  378.  */
  379. void set_normch(INFILE * inpf, BOOL(*isncfn) (int ch))
  380. {
  381.     if (inpf)
  382.         inpf->is_nc = isncfn;
  383. }
  384.  
  385. /*
  386.  *-------------------------------------
  387.  * functions for open & close
  388.  *-------------------------------------
  389.  */
  390.  
  391. /*
  392.  * infclose1
  393.  *
  394.  * close INFILE entry, free all mem allocated by it
  395.  *
  396.  * result: always 0
  397.  *
  398.  */
  399. int infclose1(INFILE * inpf)
  400. {
  401.     del_infile(inpf);
  402.  
  403.     return (0);
  404. }
  405.  
  406. /*
  407.  * infopen
  408.  *
  409.  * params: name.......name of input file to open
  410.  *         step_size..portion of memory buffers should be increased with
  411.  * result: ptr to INFILE entry or NULL if error;
  412.  *
  413.  * NOTE: if result = NULL, but errno=0, too, then there
  414.  *       wasn't enough mem for the line-buffer. in this
  415.  *       case, calling perror() will not produce a proper
  416.  *       error message.
  417.  *
  418.  * NOTE: don't forget to set errno=0 before calling infopen().
  419.  */
  420. INFILE *infopen(CONSTRPTR name, size_t step_size)
  421. {
  422. #define FILEMODE "rb"
  423. #define INF_DEFAULT_HUNKSIZE (32*1024)
  424.     INFILE *inpf = NULL;
  425.     FILE *file = NULL;
  426.     long int filesize = 0;
  427.     size_t buf_size = 4096;
  428.  
  429.     /* open input file or assign stdin to input file */
  430.     if (name)
  431.     {
  432.         file = fopen(name, FILEMODE);
  433.         if (file)
  434.         {
  435.             /* evaluate size of file and set
  436.              * buf_size accroding to it. */
  437.  
  438.             fseek(file, 0, SEEK_END);
  439.             filesize = ftell(file);
  440.             if (filesize == -1)
  441.                 buf_size = INF_DEFAULT_HUNKSIZE;
  442.             else
  443.                 buf_size = filesize + (filesize / 16) + 1;
  444.             rewind(file);
  445.             D(fprintf(stderr, "*infile* file=%ld -> bufsz=%lu, wdsz=%lu \n",
  446.                       filesize, buf_size, step_size));
  447.         }
  448.     }
  449.     else
  450.     {
  451.         file = stdin;
  452.         buf_size = INF_DEFAULT_HUNKSIZE;
  453.     }
  454.  
  455.     /* init infile */
  456.     if (file)
  457.     {
  458.         inpf = init_infile(name, buf_size, step_size);
  459.         if (inpf)
  460.             inpf->infile = file;
  461.     }
  462.  
  463.     /* read whole file into file lnbuf */
  464.     if (inpf)
  465.     {
  466.         if (file != stdin)
  467.         {
  468.             /* read whole file into buffer directly */
  469.             /* (perverted and experimental, but faaast) */
  470.             D(fprintf(stderr, "*infile*  filesize=%ld\n", filesize));
  471.             filesize = fread(inpf->lnbuf->es_data, 1, (size_t) filesize, file);
  472.             inpf->lnbuf->es_len = (size_t) filesize;
  473.             inpf->lnbuf->es_data[filesize] = 0;
  474.         }
  475.         else
  476.         {
  477.             /* read stdin, line by line */
  478.             STRPTR buf = (STRPTR) umalloc(INF_FGETS_BUFSIZE);   /* alloc buffer */
  479.             STRPTR restr = buf; /* result of fgets() (dummy init) */
  480.             BOOL ok = (buf != NULL);
  481.  
  482.             D(fprintf(stderr, "*infile*  filesize=STDIN\n"));
  483.             while (!feof(inpf->infile) && ok)
  484.             {
  485.                 restr = fgets(buf, INF_FGETS_BUFSIZE, inpf->infile);
  486.                 if (restr)
  487.                 {
  488.                     ok = app_estr(inpf->lnbuf, restr);
  489.                     D(
  490.                          {
  491.                          restr[20] = 0;
  492.                          fprintf(stderr, "*infile*  line=`%s'\n", restr);
  493.                          }
  494.                     );
  495.                 }
  496.             }
  497.  
  498.             ufree(buf);         /* free buffer */
  499.         }
  500.         D(fprintf(stderr, "*infile*  file read\n"));
  501.     }
  502.  
  503.     return (inpf);              /* return input file */
  504. }
  505.  
  506. /*
  507.  * infopen_str
  508.  *
  509.  * open a string as an input file
  510.  *
  511.  * params: fname......pseudo filename the string should have
  512.  *         s..........string that should be handled as a file
  513.  *         step_size..portion of memory buffers should be increased with
  514.  * result: ptr to INFILE entry or NULL if error;
  515.  *
  516.  * NOTE: a copy of the passed string is created. so you can
  517.  *       modify or release the string after calling inopen_str()
  518.  */
  519. INFILE *infopen_str(CONSTRPTR name, CONSTRPTR s, size_t step_size)
  520. {
  521.     /* init file */
  522.     INFILE *inpf = init_infile(name, strlen(s) + 1, step_size);
  523.  
  524.     if (inpf)
  525.     {
  526.         /* copy string to line buffer */
  527.         BOOL ok = set_estr(inpf->lnbuf, s);
  528.  
  529.         if (!ok)
  530.         {
  531.             del_infile(inpf);
  532.             inpf = NULL;
  533.         }
  534.     }
  535.  
  536.     return (inpf);              /* return input file */
  537. }
  538.  
  539. /*
  540.  *-------------------------------------
  541.  * functions to get text from infile
  542.  *-------------------------------------
  543.  */
  544.  
  545. /*
  546.  * ugly_infgetc
  547.  *
  548.  *
  549.  */
  550. int ugly_infgetc(INFILE * inpf)
  551. {
  552.     int result = EOF;
  553.  
  554. #if 0
  555.     fprintf(stderr, "** ingetch( \"%s\" at %p\n", inpf->filename, inpf);
  556. #endif
  557.     if (inpf && (!inpf->eof_reached))
  558.     {
  559.         STRPTR lnbuf_str = estr2str(inpf->lnbuf);
  560.  
  561.         /*
  562.          * if at end of line buffer, scan next line
  563.          * before proceding
  564.          */
  565.         if (lnbuf_str[inpf->filepos] == 0)
  566.         {
  567.             inpf->eof_reached = TRUE;
  568.         }
  569.  
  570.         /*
  571.          * check wether to return EOF or char from
  572.          * line buffer
  573.          */
  574.         if (inpf->eof_reached == FALSE)
  575.         {
  576.             lnbuf_str = estr2str(inpf->lnbuf);
  577.             result = lnbuf_str[inpf->filepos];  /* set last char as result */
  578.             if (result)
  579.             {                   /* goto next char in buf */
  580.                 inpf->pos_x++;
  581.                 inpf->filepos++;
  582.             }
  583.         }
  584.  
  585.         /* update line number */
  586.         if (result == '\n')
  587.         {
  588.             inpf->pos_y++;
  589.             inpf->pos_x = 0;
  590.         }
  591.     }
  592.  
  593.     return (result);
  594. }
  595.  
  596. /*
  597.  * infgetc
  598.  *
  599.  * read next char from file, update word-position
  600.  */
  601. int infgetc(INFILE * inpf)
  602. {
  603.     /* read char */
  604.     int ch = ugly_infgetc(inpf);
  605.  
  606.     /* store word position */
  607.     inpf->wpos_x = inpf->pos_x;
  608.     inpf->wpos_y = inpf->pos_y;
  609.  
  610.     /* TODO: this is shit */
  611.     if (ch=='\n')
  612.     {
  613.         inpf->wpos_y--;
  614.     }
  615.  
  616.     return (ch);
  617. }
  618.  
  619. /*
  620.  *-------------------------------------
  621.  * functions to unget text from infile
  622.  *-------------------------------------
  623.  */
  624.  
  625. /*
  626.  * inungetc
  627.  *
  628.  * write char back to stream; comparable to ansi's ungetc()
  629.  *
  630.  * params: inpf...input file
  631.  *         ch.....char to write back
  632.  * result: ch, if sucessful, else EOF
  633.  */
  634. int inungetc(int ch, INFILE * inpf)
  635. {
  636.     int result = EOF;
  637.  
  638.     if (inpf && (inpf->filepos))
  639.     {
  640.         STRPTR lnbuf_str = estr2str(inpf->lnbuf);
  641.  
  642.         /* update file position */
  643.         inpf->filepos--;
  644.  
  645.         /* write back char */
  646.         lnbuf_str[inpf->filepos] = ch;
  647.         result = ch;
  648.  
  649.         /* handle LF */
  650.         if (ch == '\n')
  651.         {
  652.             result = ch;
  653.             inpf->pos_y--;
  654.             inpf->pos_x = 0;
  655.         }
  656.         else if (inpf->pos_x)
  657.             inpf->pos_x--;
  658.     }
  659.  
  660.     return (result);
  661. }
  662.  
  663. /*
  664.  * inungets
  665.  * write string back to stream
  666.  *
  667.  * params: s......string to write back
  668.  *         inpf...input file
  669.  * result: num of chars written back
  670.  */
  671. size_t inungets(STRPTR s, INFILE * inpf)
  672. {
  673.     size_t ctr = 0;             /* counter, how many chars already written */
  674.     size_t slen = strlen(s);
  675.     STRPTR p = s + (strlen(s) - 1);     /* ptr to current char in string */
  676.     int ch = 0;                 /* current char written, dummy init */
  677.  
  678.     if (slen > 0)
  679.     {
  680.         ctr = 1;                /* unget first char */
  681.         ch = inungetc(p[0], inpf);
  682.  
  683.         while ((p != s) && (ch != EOF))
  684.         {
  685.             ctr++;              /* inc counter */
  686.             p--;                /* goto next char */
  687.             ch = inungetc(p[0], inpf);  /* unget current char */
  688.         }
  689.     }
  690.  
  691.     return (ctr);
  692. }
  693.  
  694. /*
  695.  * inungetcw
  696.  * write current word back to stream
  697.  *
  698.  * params: inpf...input file
  699.  * result: num of chars written back
  700.  */
  701. size_t inungetcw(INFILE * inpf)
  702. {
  703.     size_t ctr;                 /* counter how many chars written */
  704.  
  705.     /* unget word */
  706.     ctr = inungets(infgetcw(inpf), inpf);
  707.  
  708.     return (ctr);
  709. }
  710.  
  711. /*
  712.  * inungetcwws
  713.  * write current word & whitespaces back to stream
  714.  *
  715.  * params: inpf...input file
  716.  * result: num of chars written back
  717.  */
  718. size_t inungetcwws(INFILE * inpf)
  719. {
  720.     size_t ctr;                 /* counter how many chars written */
  721.  
  722.     /* unget word & white spaces */
  723.     ctr = inungets(infgetcw(inpf), inpf);
  724.     ctr += inungets(infgetcws(inpf), inpf);
  725.  
  726.     return (ctr);
  727. }
  728.  
  729. /*
  730.  * inf_isws
  731.  *
  732.  * checks if a char is a white space
  733.  *
  734.  * params: ch...char to check for white space
  735.  * result: TRUE if ch was white space
  736.  */
  737. BOOL inf_isws(char ch, INFILE * inpf)
  738. {
  739.     BOOL(*isws) (int ch) = inpf->is_ws;
  740.  
  741.     if (isws == NULL)           /* if no func for is_ws, */
  742.         isws = default_whtspc;  /*   set default function */
  743.  
  744.     return ((*isws) (ch));
  745. }
  746.  
  747. /*
  748.  * infskip_ws
  749.  *
  750.  * skip white spaces; update wspbuf; clear wordbuf
  751.  *
  752.  * TODO: handle wspcbuf-overflow
  753.  */
  754. size_t infskip_ws(INFILE * inpf)
  755. {
  756.     char nxtch;                 /* next char to read */
  757.     size_t ctr = 0;             /* num of ws skipped */
  758.     BOOL ok;
  759.  
  760.     /*
  761.      * set function to determine if a
  762.      * specified char is a white space
  763.      */
  764.     inpf->skipped_ws = FALSE;   /* clear skippe-flag */
  765.  
  766.     /* clear wspcbuf */
  767.     ok = clr_estr(inpf->wspcbuf);
  768.  
  769.     /*
  770.      * loop:  skip white spaces
  771.      */
  772.     nxtch = ugly_infgetc(inpf); /* read next char */
  773.     while ((!infeof(inpf))      /* while not at end of file.. */
  774.            && ok
  775.            && inf_isws(nxtch, inpf))    /* ..and current char is a whtspc */
  776.     {
  777.         ok &= app_estrch(inpf->wspcbuf, nxtch);
  778.         ctr++;
  779.         nxtch = ugly_infgetc(inpf);     /*   read next char */
  780.     }
  781.  
  782.     if (ctr)                    /* any whtspcs skipped? */
  783.         inpf->skipped_ws = TRUE;        /* Y-> set skippe-flag */
  784.  
  785. #if 0
  786.     if (!ok)
  787.         /* TODO: error */ ;
  788. #endif
  789.  
  790.     /*
  791.      * write back last char read
  792.      */
  793.     inungetc(nxtch, inpf);
  794.  
  795.     return (ctr);
  796. }
  797.  
  798. /*
  799.  * infgetall
  800.  *
  801.  * returns whole text
  802.  */
  803. STRPTR infgetall(INFILE * inpf)
  804. {
  805.     return (estr2str(inpf->lnbuf));
  806. }
  807.  
  808. /*
  809.  * infgetw
  810.  *
  811.  * read word
  812.  */
  813. STRPTR infgetw(INFILE * inpf)
  814. {
  815.     /* TODO: handle expstr errors */
  816.     int ch = EOF;
  817.     BOOL wordread = FALSE;
  818.     STRPTR thisword = NULL;
  819.     BOOL ok = TRUE;
  820.  
  821.     /* set function for normal chars */
  822.     BOOL(*isnc) (int ch) = inpf->is_nc;
  823.     if (isnc == NULL)
  824.         isnc = default_normch;
  825.  
  826.     /* skip all white spaces */
  827.     infskip_ws(inpf);
  828.  
  829.     ok = clr_estr(inpf->wordbuf);
  830.  
  831.     /*
  832.      * read word until non-normal char is reached
  833.      */
  834.     if (!infeof(inpf))
  835.     {
  836.         ch = infgetc(inpf);
  837.  
  838.         if (((*isnc) (ch)))
  839.             do
  840.             {
  841.                 ok &= app_estrch(inpf->wordbuf, ch);
  842.                 ch = ugly_infgetc(inpf);
  843.                 wordread = TRUE;
  844.                 /* todo: set out-of-mem-flag */
  845.             }
  846.             while ((ch != EOF) && ok && ((*isnc) (ch)));
  847.         else
  848.             ok &= app_estrch(inpf->wordbuf, ch);
  849.  
  850.         if ((ch != EOF) && (wordread))
  851.             inungetc(ch, inpf);
  852.  
  853.         thisword = estr2str(inpf->wordbuf);
  854.     }
  855.     else
  856.         thisword = NULL;
  857.  
  858.     return (thisword);
  859. }
  860.  
  861. /*
  862.  * infgotoeol
  863.  *
  864.  * read all chars until CR or EOF
  865.  */
  866. int infgotoeol(INFILE * inpf)
  867. {
  868.     int ch = EOF;
  869.  
  870.     if (!infeof(inpf))
  871.     {
  872.         /*
  873.          * read all chars until CR appears
  874.          */
  875.         do
  876.         {
  877.             ch = ugly_infgetc(inpf);
  878.         }
  879.         while ((ch > 0) && (ch != 0x0a));
  880.  
  881.         /*
  882.          * read LF
  883.          */
  884.         if (ch == 0x0a)
  885.         {
  886.             ch = ugly_infgetc(inpf);
  887.             if (ch != 0x0d)
  888.                 inungetc(ch, inpf);
  889.             ch = 0x0a;
  890.         }
  891.     }
  892.  
  893.     /* return last char read */
  894.     return (ch);
  895. }
  896.  
  897. /*
  898.  *-------------------------------------
  899.  * functions for file-positions
  900.  *-------------------------------------
  901.  */
  902.  
  903. /*
  904.  * del_infilepos_nddata
  905.  */
  906. static VOID del_infilepos_nddata(APTR data)
  907. {
  908.     INFILEPOS *pos = (INFILEPOS *) data;
  909.  
  910.     if (pos)
  911.     {
  912.         /* decrese number of pending pos-requests */
  913.         (pos->inpf->pos_count)--;
  914.  
  915.         D(fprintf(stderr, DINF "del pos-req: \"%s\" (%lu,%lu); %lu left\n",
  916.                   pos->inpf->filename ? pos->inpf->filename : (STRPTR) "STDIN",
  917.                   pos->x, pos->y, pos->inpf->pos_count));
  918.  
  919.         /* free resources alloceted by pos-request */
  920.         ufree(pos);
  921.     }
  922. }
  923.  
  924. /*
  925.  * find_posnd
  926.  */
  927. static int cmp_posdata(APTR data1, APTR data2)
  928. {
  929.     if (data1 == data2)
  930.         return (-1);
  931.     else
  932.         return (0);
  933. }
  934.  
  935. /*
  936.  * del_infilepos
  937.  */
  938. VOID del_infilepos(INFILEPOS * pos)
  939. {
  940.     if (pos)
  941.     {
  942.         INFILE *inpf = pos->inpf;
  943.  
  944.         /* remove filename */
  945.         ufreestr(pos->fname);
  946.  
  947.         /* check, if file has already been closed by user,
  948.          * but the last pos-requests has just been deleted
  949.          * now.
  950.          * if so, really close the file now
  951.          */
  952.         if ((inpf->closed)
  953.             && (inpf->pos_count == 1)
  954.             )
  955.         {
  956.             D(fprintf(stderr, DINF "  really closing file:\n"));
  957.             (pos->inpf->pos_count)--;
  958.             infclose1(inpf);
  959.         }
  960.         else
  961.         {
  962.             DLNODE *nd = find_dlnode(dll_first(pos->inpf->pos_list),
  963.                                      pos, cmp_posdata);
  964.             del_dlnode(pos->inpf->pos_list, nd);
  965.         }
  966.     }
  967. }
  968.  
  969. /*
  970.  * del_all_infilepos
  971.  */
  972. VOID del_all_infilepos(INFILE * inpf)
  973. {
  974.     del_all_dlnodes(inpf->pos_list);
  975. }
  976.  
  977. /*
  978.  * new_infilepos
  979.  */
  980. static INFILEPOS *new_infilepos_node(INFILE * inpfile, ULONG x, ULONG y)
  981. {
  982.     INFILEPOS *pos = umalloc(sizeof(INFILEPOS));
  983.  
  984.     if (pos)
  985.     {
  986.         DLNODE *nd = app_dlnode(inpfile->pos_list, pos);
  987.  
  988.         pos->inpf = inpfile;
  989.         pos->fname = strclone(inpfile->filename);
  990.         pos->x = x;
  991.         pos->y = y;
  992.         pos->fpos = inpfile->filepos;
  993.  
  994.         if (!nd)
  995.         {
  996.             del_infilepos_nddata(pos);
  997.             pos = NULL;
  998.         }
  999.         else
  1000.         {
  1001.             (inpfile->pos_count)++;
  1002.         }
  1003.     }
  1004.  
  1005. #if DEBUG_UGLY_INFILE
  1006.     {
  1007.         if (pos)
  1008.         {
  1009.             fprintf(stderr, DINF "new pos-req: \"%s\" (%d,%d); #%d\n",
  1010.                     inpf->filename ? inpf->filename : "STDIN",
  1011.                     inpfile->pos_x, inpfile->pos_y, inpfile->pos_count);
  1012.         }
  1013.         else
  1014.         {
  1015.             fprintf(stderr, DINF "new pos-req FAILED\n");
  1016.         }
  1017.     }
  1018. #endif
  1019.  
  1020.     return pos;
  1021. }
  1022.  
  1023. INFILEPOS *new_infilepos(INFILE * inpfile)
  1024. {
  1025.     INFILEPOS *pos =
  1026.     new_infilepos_node(inpfile, inpfile->pos_x, inpfile->pos_y);
  1027.     return pos;
  1028. }
  1029.  
  1030. INFILEPOS *new_winfilepos(INFILE * inpfile)
  1031. {
  1032.     INFILEPOS *pos =
  1033.     new_infilepos_node(inpfile, inpfile->wpos_x, inpfile->wpos_y);
  1034.     return pos;
  1035. }
  1036.  
  1037. /*
  1038.  * get methodes for pos-req
  1039.  */
  1040. STRPTR ifp_get_fname(INFILEPOS * pos)
  1041. {
  1042.     return (infget_fname(pos->inpf));
  1043. }
  1044.  
  1045. ULONG ifp_get_x(INFILEPOS * pos)
  1046. {
  1047.     return (pos->x);
  1048. }
  1049.  
  1050. ULONG ifp_get_y(INFILEPOS * pos)
  1051. {
  1052.     return (pos->y);
  1053. }
  1054.  
  1055. BOOL set_infile_base(INFILE * inpf, INFILEPOS * pos)
  1056. {
  1057.     D(fprintf(stderr, DINF "set base \"%s\" to \"%s\" (%lu,%lu)\n",
  1058.               inpf->filename ? inpf->filename : (STRPTR) "STDIN",
  1059.               pos->inpf->filename ? pos->inpf->filename : (STRPTR) "STDIN",
  1060.               pos->x, pos->y));
  1061.     reallocstr(&(inpf->filename), pos->fname);
  1062.     inpf->base_x = pos->x;
  1063.     inpf->base_y = pos->y + 1;
  1064.     return (TRUE);              /* TODO: handle out of mem */
  1065. }
  1066.  
  1067. BOOL set_infilepos(INFILE * inpf, INFILEPOS * pos)
  1068. {
  1069.     D(fprintf(stderr, DINF "set pos  \"%s\" to \"%s\" (%lu,%lu)\n",
  1070.               inpf->filename ? inpf->filename : (STRPTR) "STDIN",
  1071.               pos->inpf->filename ? pos->inpf->filename : (STRPTR) "STDIN",
  1072.               pos->x, pos->y));
  1073.     reallocstr(&(inpf->filename), pos->fname);
  1074.     inpf->pos_x = pos->x;
  1075.     inpf->pos_y = pos->y;
  1076.     inpf->wpos_x = pos->x;
  1077.     inpf->wpos_y = pos->y;
  1078.     return (TRUE);              /* TODO: handle out of mem */
  1079. }
  1080.  
  1081.